package com.cryptoneedle.garden.service.garden.source;


import com.cryptoneedle.garden.entity.source.metadata.SourceCatalog;
import com.cryptoneedle.garden.entity.source.metadata.SourceDatabase;
import com.cryptoneedle.garden.service.crud.garden.source.*;
import com.cryptoneedle.garden.service.garden.source.constraint.*;
import com.cryptoneedle.garden.service.garden.source.enhance.DimensionService;
import com.cryptoneedle.garden.service.garden.source.enhance.TransService;
import com.cryptoneedle.garden.service.garden.source.metadata.ColumnService;
import com.cryptoneedle.garden.service.garden.source.metadata.DatabaseService;
import com.cryptoneedle.garden.service.garden.source.metadata.TableService;
import jakarta.annotation.Resource;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.List;

/**
 * <p>description: 源数据源-同步服务 </p>
 *
 * @author CryptoNeedle
 * @date 2025-06-23
 */
@Slf4j
@Service
public class SourceSyncService {

    @Autowired
    private FoundSourceService select;
    @Autowired
    private AddSourceService add;
    @Autowired
    private PatchSourceService patch;
    @Autowired
    private SaveSourceService save;
    @Autowired
    private DeleteSourceService delete;

    @Resource
    private ConnectionService connectionService;
    @Resource
    private SourceSyncService sourceSyncService;
    @Resource
    private DatabaseService databaseService;
    @Resource
    private TableService tableService;
    @Resource
    private ColumnService columnService;
    @Resource
    private ConstraintPrimaryService constraintPrimaryService;
    @Resource
    private ConstraintUniqueService constraintUniqueService;
    @Resource
    private ConstraintForeignService constraintForeignService;
    @Resource
    private ConstraintCheckService constraintCheckService;
    @Resource
    private IndexUniqueService indexUniqueService;

    @Resource
    private DimensionService dimensionService;
    @Resource
    private TransService transService;

    public void syncSource() {
        List<SourceCatalog> catalogs = select.catalogsEnabled();
        for (SourceCatalog catalog : catalogs) {
            try {
                sourceSyncService.syncCatalog(catalog);
                log.info("[SYNC] {} -> 完成", catalog.getCatalogName());
            } catch (Exception e) {
                log.error("[SYNC] {} -> 异常 => {}", catalog.getCatalogName(), e.getMessage());
            }
        }
    }

    public void syncCatalog(SourceCatalog catalog) {
        String catalogName = catalog.getCatalogName();

        // 测试
        connectionService.testCatalog(catalog);
        if (!catalog.getServerConnected()) {
            throw new RuntimeException("[SYNC] SourceServer Connected Error");
        }
        if (!catalog.getJdbcConnected()) {
            throw new RuntimeException("[SYNC] JDBC Connected Error");
        }
        //if (!catalog.getDorisConnected()) {
        //    throw new RuntimeException("[SYNC] Doris Connected Error");
        //}

        List<SourceDatabase> databases = select.databasesEnabled(catalog);
        if (!databases.isEmpty()) {
            log.info("[SYNC] {} =======================> [开始]", catalogName);
            for (SourceDatabase database : databases) {
                sourceSyncService.syncDatabase(catalog, database);
            }
            log.info("[SYNC] {} =======================> [开始]", catalogName);
        } else {
            databaseService.syncDatabase(catalog);
        }
    }

    public void syncDatabase(String catalogName, String databaseName) {
        SourceCatalog catalog = select.catalog(catalogName);
        SourceDatabase database = select.database(catalogName, databaseName);
        sourceSyncService.syncDatabase(catalog, database);
    }


    public void syncDatabase(SourceCatalog catalog, SourceDatabase database) {
        // 元数据同步
        databaseService.syncDatabase(catalog, database);
        tableService.syncDatabase(catalog, database);
        columnService.syncDatabase(catalog, database);
        constraintPrimaryService.syncDatabase(catalog, database);
        constraintUniqueService.syncDatabase(catalog, database);
        constraintForeignService.syncDatabase(catalog, database);
        constraintCheckService.syncDatabase(catalog, database);
        indexUniqueService.syncDatabase(catalog, database);

        // todo 开启实验性的Doris全量同步数据以获取在Doris数据库中真实的存储信息
        // 基于Catalog做会简单些

        // 处理维度信息
        dimensionService.syncDatabase(catalog, database);
        // 计算数据分布策略
        transService.calcuteDataDistribute(catalog, database);
        // 转换为Doris结构
        transService.transformDatabase(catalog, database);
        // todo 任务分片
    }
}